using System;
using System.Collections.Generic;
using UnityEngine;
using Object = UnityEngine.Object;

namespace UFE3D.UI
{
    public interface IUIElementItem<TItemInfo, TContainer>
    {
        void SetUp(TItemInfo itemInfo, TContainer container, int index);
        void CleanUp();
    }
    
    
    public static class UIElementListFillHelper
    {
        
        public static void SetUp<TItemScript, TItemInfo, TContainer>(TItemScript itemPrefab, IList<TItemInfo> itemInfos, TContainer container,
            IList<TItemScript> result = null, Func<TItemScript, TItemScript> createFactory = null) where TItemScript : MonoBehaviour, IUIElementItem<TItemInfo, TContainer>
        {
            // Assert.That(itemPrefab != null, "Item prefab should not be null.");
            itemPrefab.gameObject.SetActive(false);
            
            var parent = itemPrefab.transform.parent;
            // Assert.That(parent != null, "Item prefab should put under a parent.");
            
            result?.Clear();

            int i = 0;
            foreach (Transform child in parent)
            {
                var childComp = child.GetComponent<TItemScript>();
                if (!childComp)
                {
                    continue;
                }
                
                if (childComp.GetInstanceID() == itemPrefab.GetInstanceID())
                {
                    continue;
                }

                if (child.gameObject.activeSelf)
                {
                    childComp.CleanUp();
                }

                if (i < itemInfos.Count)
                {
                    childComp.SetUp(itemInfos[i], container, i);
                    i++;
                    
                    childComp.gameObject.SetActive(true);
                    result?.Add(childComp);
                }
                else
                {
                    childComp.gameObject.SetActive(false);
                }
            }

            for (; i < itemInfos.Count; i++)
            {
                TItemScript childInst = null;
                if (createFactory != null)
                {
                    childInst = createFactory.Invoke(itemPrefab);
                    childInst.transform.SetParent(parent, false);
                }
                else
                {
                    childInst = Object.Instantiate<TItemScript>(itemPrefab, parent, false);
                }
                
                // Make sure Awake function called before SetUp, due to some SetUp function may require Awake initialization.
                childInst.gameObject.SetActive(true);
                childInst.SetUp(itemInfos[i], container, i);
                result?.Add(childInst);
            }
        }
        
        public static void CleanUp<TItemScript, TItemInfo, TContainer>(TItemScript itemPrefab) where TItemScript : MonoBehaviour, IUIElementItem<TItemInfo, TContainer>
        {
            // Assert.That(itemPrefab != null, "Item prefab should not be null.");
            
            var parent = itemPrefab.transform.parent;
            // Assert.That(parent != null, "Item prefab should put under a parent.");

            itemPrefab.gameObject.SetActive(false);

            foreach (Transform child in parent)
            {
                if (!child.gameObject.activeSelf)
                {
                    continue;
                }
                
                var childComp = child.GetComponent<TItemScript>();
                if (!childComp || childComp.GetInstanceID() == itemPrefab.GetInstanceID())
                {
                    continue;
                }
                
                childComp.CleanUp();
                child.gameObject.SetActive(false);
            }
        }
        
    }
}